/* -------------------------------------------------------------------------
 *
 * pg_regress_ecpg --- regression test driver for ecpg
 *
 * This is a C implementation of the previous shell script for running
 * the regression tests, and should be mostly compatible with it.
 * Initial author of C translation: Magnus Hagander
 *
 * This code is released under the terms of the PostgreSQL License.
 *
 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/interfaces/ecpg/test/pg_regress_ecpg.c
 *
 * -------------------------------------------------------------------------
 */

#include "pg_regress.h"

#define LINEBUFSIZE 300
static void ecpg_filter(const char* sourcefile, const char* outfile)
{
    /*
     * Create a filtered copy of sourcefile, replacing #line x
     * "./../bla/foo.h" with #line x "foo.h"
     */
    FILE *s, *t;
    char linebuf[LINEBUFSIZE];

    s = fopen(sourcefile, "r");
    if (!s) {
        fprintf(stderr, "Could not open file %s for reading\n", sourcefile);
        exit(2);
    }
    t = fopen(outfile, "w");
    if (!t) {
        fprintf(stderr, "Could not open file %s for writing\n", outfile);
        exit(2);
    }

    while (fgets(linebuf, LINEBUFSIZE, s)) {
        /* check for "#line " in the beginning */
        if (strstr(linebuf, "#line ") == linebuf) {
            char* p = strchr(linebuf, '"');
            char* n = NULL;
            int plen = 1;

            while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL)) {
                plen++;
            }
            /* plen is one more than the number of . and / characters */
            if (plen > 1) {
                n = (char*)malloc(plen);
                strncpy(n, p + 1, plen - 1);
                n[plen - 1] = '\0';
                replace_string(linebuf, n, "");
                free(n);
                n = NULL;
            }
        }
        fputs(linebuf, t);
    }
    fclose(s);
    fclose(t);
}

/*
 * start an ecpg test process for specified file (including redirection),
 * and return process ID
 */

static PID_TYPE ecpg_start_test(
    const char* testname, _stringlist** resultfiles, _stringlist** expectfiles, _stringlist** tags,
    bool use_jdbc_client)
{
    PID_TYPE pid;
    char inprg[MAXPGPATH];
    char insource[MAXPGPATH];
    char *outfile_stdout, expectfile_stdout[MAXPGPATH];
    char *outfile_stderr, expectfile_stderr[MAXPGPATH];
    char *outfile_source, expectfile_source[MAXPGPATH];
    char cmd[MAXPGPATH * 3];
    char* testname_dash = NULL;

    snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);

    testname_dash = strdup(testname);
    replace_string(testname_dash, "/", "-");
    snprintf(expectfile_stdout, sizeof(expectfile_stdout), "%s/expected/%s.stdout", outputdir, testname_dash);
    snprintf(expectfile_stderr, sizeof(expectfile_stderr), "%s/expected/%s.stderr", outputdir, testname_dash);
    snprintf(expectfile_source, sizeof(expectfile_source), "%s/expected/%s.cpp", outputdir, testname_dash);
    free(testname_dash);
    testname_dash = NULL;

    /*
     * We can use replace_string() here because the replacement string does
     * not occupy more space than the replaced one.
     */
    outfile_stdout = strdup(expectfile_stdout);
    replace_string(outfile_stdout, "/expected/", "/results/");
    outfile_stderr = strdup(expectfile_stderr);
    replace_string(outfile_stderr, "/expected/", "/results/");
    outfile_source = strdup(expectfile_source);
    replace_string(outfile_source, "/expected/", "/results/");

    add_stringlist_item(resultfiles, outfile_stdout);
    add_stringlist_item(expectfiles, expectfile_stdout);
    add_stringlist_item(tags, "stdout");

    add_stringlist_item(resultfiles, outfile_stderr);
    add_stringlist_item(expectfiles, expectfile_stderr);
    add_stringlist_item(tags, "stderr");

    add_stringlist_item(resultfiles, outfile_source);
    add_stringlist_item(expectfiles, expectfile_source);
    add_stringlist_item(tags, "cpp");

    snprintf(insource, sizeof(insource), "%s.cpp", testname);
    ecpg_filter(insource, outfile_source);

    snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);

    snprintf(
        cmd, sizeof(cmd), SYSTEMQUOTE "\"%s\" >\"%s\" 2>\"%s\"" SYSTEMQUOTE, inprg, outfile_stdout, outfile_stderr);

    pid = spawn_process(cmd);

    if (pid == INVALID_PID) {
        fprintf(stderr, _("could not start process for test %s\n"), testname);
        exit(2);
    }

    free(outfile_stdout);
    free(outfile_stderr);
    free(outfile_source);

    return pid;
}

static void ecpg_init(void)
{
    /* nothing to do here at the moment */
}

int main(int argc, char* argv[])
{
    return regression_main(argc, argv, ecpg_init, ecpg_start_test, NULL);
}
